//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Eas.WebCrawler.Interfaces;
using Eas.WebCrawler.Model;
using NMock2;

namespace Eas.WebCrawler.Test.Model {
    /// <summary>
    /// Summary description for StorageWriterTest
    /// </summary>
    [TestClass]
    public class StorageWriterTest {
        Mockery _Mockery;
        Eas.WebCrawler.Interfaces.TemporaryStorage _Storage;

        public StorageWriterTest() {
            //
            // TODO: Add constructor logic here
            //
        }

        #region Additional test attributes
        // 
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }

        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() {
            _Mockery = new Mockery();
            _Storage = _Mockery.NewMock<Eas.WebCrawler.Interfaces.TemporaryStorage>();

        }

        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup() {
            _Storage = null;
            _Mockery.Dispose();
            _Mockery = null;
        }

        #endregion

        [TestMethod]
        /// <summary>Executes the TestTextHello test.</summary>
        public void TestTextHello() {
            string test = "hello";
            PerformTextTest(test);
        }

        [TestMethod]
        /// <summary>Executes the TestBinaryHello test.</summary>
        public void TestBinaryHello() {
            string test = "hello";
            PerformBinaryTest(test);
        }

        [TestMethod]
        /// <summary>Executes the TestTextHellow test.</summary>
        public void TestTextHellow() {
            string test = "hellow";
            PerformTextTest(test);
        }

        [TestMethod]
        /// <summary>Executes the TestBinaryHellow test.</summary>
        public void TestBinaryHellow() {
            string test = "hellow";
            PerformBinaryTest(test);
        }


        private void PerformBinaryTest(string test) {
            using (Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage _store = new Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage()) {
                System.IO.BinaryWriter binaryWriter = _store.GetBinaryWriter();
                Expect.Once.On(_Storage).Method("GetBinaryWriter").WithNoArguments().Will(Return.Value(binaryWriter));
                using (Eas.WebCrawler.Model.StorageWriters.BinaryStorageWriter bw = new Eas.WebCrawler.Model.StorageWriters.BinaryStorageWriter()) {
                    bw.Initialize(_Storage);
                    TestWriter(bw, test);
                }
                string newString;
                using (System.IO.BinaryReader reader = _store.GetBinaryReader()) {
                    byte[] bytes = reader.ReadBytes(30000);
                    newString = new string(System.Text.Encoding.ASCII.GetChars(bytes));
                }
                Assert.AreEqual<string>(test, newString);
            }
        }

        private void PerformTextTest(string test) {
            using (Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage _store = new Eas.WebCrawler.PlugIns.TemporaryStorage.MemoryStorage()) {
                System.IO.TextWriter textWriter = _store.GetTextWriter();
                Expect.Once.On(_Storage).Method("GetTextWriter").WithNoArguments().Will(Return.Value(textWriter));
                using (Eas.WebCrawler.Model.StorageWriters.TextStorageWriter tw = new Eas.WebCrawler.Model.StorageWriters.TextStorageWriter()) {
                    tw.Initialize(_Storage);
                    TestWriter(tw, test);
                }
                string newString;
                using (System.IO.TextReader reader = _store.GetTextReader()) {
                    newString = reader.ReadToEnd();
                }
                Assert.AreEqual<string>(test, newString);
            }
        }

        private void TestWriter(Eas.WebCrawler.Model.StorageWriters.StorageWriter writer, string text) {
            byte[] buffer = System.Text.Encoding.ASCII.GetBytes(text);
            int length = buffer.Length;
            bool extra = (length % 2 == 1);
            int pairs = length / 2;

            for (int i = 0; i < pairs; i++) {
                byte[] pair = new byte[i + 2];
                pair[0] = buffer[i * 2];
                pair[1] = buffer[(i * 2) + 1];
                writer.Add(pair, 2);
            }
            if (extra) {
                byte[] pair = new byte[1];
                pair[0] = buffer[buffer.Length - 1];
                writer.Add(pair, 1);
            }
        }
    }
}
